﻿Imports System
Imports System.CodeDom
Imports System.ComponentModel
Imports System.ComponentModel.Design
Imports System.Diagnostics.CodeAnalysis
Imports System.Drawing
Imports System.Globalization
Imports System.Reflection
Imports System.Windows.Forms
Imports System.Windows.Forms.Design
Imports System.Workflow.Activities.Rules
Imports System.Workflow.ComponentModel
Imports System.Workflow.ComponentModel.Compiler
Imports System.Workflow.ComponentModel.Design

Namespace System.Workflow.Activities.Rules.Design
    Public Class RuleConditionDialog
        Inherits Form
        ' Methods
        Public Sub New(ByVal activity As Activity, ByVal expression As CodeExpression)
            Dim provider As ITypeProvider
            Me.ruleExpressionCondition = New RuleExpressionCondition
            If (activity Is Nothing) Then
                Throw New ArgumentNullException("activity")
            End If
            Me.InitializeComponent
            Me.serviceProvider = activity.Site
            If (Not Me.serviceProvider Is Nothing) Then
                Dim service As IUIService = [TryCast](Me.serviceProvider.GetService(GetType(IUIService)),IUIService)
                If (Not service Is Nothing) Then
                    Me.Font = DirectCast(service.Styles.Item("DialogFont"), Font)
                End If
                provider = DirectCast(Me.serviceProvider.GetService(GetType(ITypeProvider)), ITypeProvider)
                If (provider Is Nothing) Then
                    Throw New InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Messages.MissingService, New Object() { GetType(ITypeProvider).FullName }))
                End If
                Dim loader As WorkflowDesignerLoader = [TryCast](Me.serviceProvider.GetService(GetType(WorkflowDesignerLoader)),WorkflowDesignerLoader)
                If (Not loader Is Nothing) Then
                    loader.Flush
                End If
            Else
                Dim provider2 As New TypeProvider(Nothing)
                Dim assembly As Assembly
                For Each assembly In AppDomain.CurrentDomain.GetAssemblies
                    provider2.AddAssembly([assembly])
                Next
                provider = provider2
            End If
            Dim validation As New RuleValidation(activity, provider, False)
            Me.ruleParser = New Parser(validation)
            Me.InitializeDialog(expression)
        End Sub

        Public Sub New(ByVal activityType As Type, ByVal typeProvider As ITypeProvider, ByVal expression As CodeExpression)
            Me.ruleExpressionCondition = New RuleExpressionCondition
            If (activityType Is Nothing) Then
                Throw New ArgumentNullException("activityType")
            End If
            Me.InitializeComponent
            Dim validation As New RuleValidation(activityType, typeProvider)
            Me.ruleParser = New Parser(validation)
            Me.InitializeDialog(expression)
        End Sub

        Private Sub ConditionTextBox_PopulateAutoCompleteList(ByVal sender As Object, ByVal e As AutoCompletionEventArgs)
            e.AutoCompleteValues = Me.ruleParser.GetExpressionCompletions(e.Prefix)
        End Sub

        <SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")> _
        Private Sub conditionTextBox_Validating(ByVal sender As Object, ByVal e As CancelEventArgs)
            Try 
                Me.ruleExpressionCondition = Me.ruleParser.ParseCondition(Me.conditionTextBox.Text)
                If Not String.IsNullOrEmpty(Me.conditionTextBox.Text) Then
                    Me.conditionTextBox.Text = Me.ruleExpressionCondition.ToString.Replace(ChrW(10), ChrW(13) & ChrW(10))
                End If
                Me.conditionErrorProvider.SetError(Me.conditionTextBox, String.Empty)
                Me.syntaxException = Nothing
            Catch exception As Exception
                Me.syntaxException = exception
                Me.conditionErrorProvider.SetError(Me.conditionTextBox, exception.Message)
            End Try
        End Sub

        Protected Overrides Sub Dispose(ByVal disposing As Boolean)
            If (disposing AndAlso (Not Me.components Is Nothing)) Then
                Me.components.Dispose
            End If
            MyBase.Dispose(disposing)
        End Sub

        Private Sub InitializeComponent()
            Me.components = New Container
            Dim manager As New ComponentResourceManager(GetType(RuleConditionDialog))
            Me.okCancelTableLayoutPanel = New TableLayoutPanel
            Me.okButton = New Button
            Me.cancelButton = New Button
            Me.headerLabel = New Label
            Me.headerPictureBox = New PictureBox
            Me.conditionTextBox = New IntellisenseTextBox
            Me.conditionLabel = New Label
            Me.conditionErrorProvider = New ErrorProvider(Me.components)
            Me.okCancelTableLayoutPanel.SuspendLayout
            DirectCast(Me.headerPictureBox, ISupportInitialize).BeginInit
            DirectCast(Me.conditionErrorProvider, ISupportInitialize).BeginInit
            MyBase.SuspendLayout
            manager.ApplyResources(Me.okCancelTableLayoutPanel, "okCancelTableLayoutPanel")
            Me.okCancelTableLayoutPanel.CausesValidation = False
            Me.okCancelTableLayoutPanel.Controls.Add(Me.okButton, 0, 0)
            Me.okCancelTableLayoutPanel.Controls.Add(Me.cancelButton, 1, 0)
            Me.okCancelTableLayoutPanel.Name = "okCancelTableLayoutPanel"
            manager.ApplyResources(Me.okButton, "okButton")
            Me.okButton.DialogResult = DialogResult.OK
            Me.okButton.Name = "okButton"
            AddHandler Me.okButton.Click, New EventHandler(AddressOf Me.okButton_Click)
            manager.ApplyResources(Me.cancelButton, "cancelButton")
            Me.cancelButton.CausesValidation = False
            Me.cancelButton.DialogResult = DialogResult.Cancel
            Me.cancelButton.Name = "cancelButton"
            manager.ApplyResources(Me.headerLabel, "headerLabel")
            Me.headerLabel.Name = "headerLabel"
            manager.ApplyResources(Me.headerPictureBox, "headerPictureBox")
            Me.headerPictureBox.Name = "headerPictureBox"
            Me.headerPictureBox.TabStop = False
            Me.conditionTextBox.AcceptsReturn = True
            manager.ApplyResources(Me.conditionTextBox, "conditionTextBox")
            Me.conditionTextBox.Name = "conditionTextBox"
            AddHandler Me.conditionTextBox.Validating, New CancelEventHandler(AddressOf Me.conditionTextBox_Validating)
            manager.ApplyResources(Me.conditionLabel, "conditionLabel")
            Me.conditionLabel.Name = "conditionLabel"
            Me.conditionErrorProvider.BlinkStyle = ErrorBlinkStyle.NeverBlink
            Me.conditionErrorProvider.ContainerControl = Me
            MyBase.AcceptButton = Me.okButton
            manager.ApplyResources(Me, "$this")
            MyBase.AutoScaleMode = AutoScaleMode.Font
            MyBase.CancelButton = Me.cancelButton
            MyBase.Controls.Add(Me.conditionLabel)
            MyBase.Controls.Add(Me.conditionTextBox)
            MyBase.Controls.Add(Me.okCancelTableLayoutPanel)
            MyBase.Controls.Add(Me.headerLabel)
            MyBase.Controls.Add(Me.headerPictureBox)
            MyBase.FormBorderStyle = FormBorderStyle.FixedDialog
            MyBase.HelpButton = True
            MyBase.MaximizeBox = False
            MyBase.MinimizeBox = False
            MyBase.Name = "RuleConditionDialog"
            MyBase.ShowInTaskbar = False
            AddHandler MyBase.FormClosing, New FormClosingEventHandler(AddressOf Me.RuleConditionDialog_FormClosing)
            Me.okCancelTableLayoutPanel.ResumeLayout(False)
            Me.okCancelTableLayoutPanel.PerformLayout
            DirectCast(Me.headerPictureBox, ISupportInitialize).EndInit
            DirectCast(Me.conditionErrorProvider, ISupportInitialize).EndInit
            MyBase.ResumeLayout(False)
            MyBase.PerformLayout
        End Sub

        Private Sub InitializeDialog(ByVal expression As CodeExpression)
            AddHandler MyBase.HelpRequested, New HelpEventHandler(AddressOf Me.OnHelpRequested)
            AddHandler MyBase.HelpButtonClicked, New CancelEventHandler(AddressOf Me.OnHelpClicked)
            If (Not expression Is Nothing) Then
                Me.ruleExpressionCondition.Expression = RuleExpressionWalker.Clone(expression)
                Me.conditionTextBox.Text = Me.ruleExpressionCondition.ToString.Replace(ChrW(10), ChrW(13) & ChrW(10))
            Else
                Me.conditionTextBox.Text = String.Empty
            End If
            AddHandler Me.conditionTextBox.PopulateAutoCompleteList, New EventHandler([Of] AutoCompletionEventArgs)(AddressOf Me.ConditionTextBox_PopulateAutoCompleteList)
            AddHandler Me.conditionTextBox.PopulateToolTipList, New EventHandler([Of] AutoCompletionEventArgs)(AddressOf Me.ConditionTextBox_PopulateAutoCompleteList)
            Try 
                Me.ruleParser.ParseCondition(Me.conditionTextBox.Text)
                Me.conditionErrorProvider.SetError(Me.conditionTextBox, String.Empty)
            Catch exception As RuleSyntaxException
                Me.conditionErrorProvider.SetError(Me.conditionTextBox, exception.Message)
            End Try
        End Sub

        Private Sub okButton_Click(ByVal sender As Object, ByVal e As EventArgs)
            Me.wasOKed = True
        End Sub

        Private Sub OnHelpClicked(ByVal sender As Object, ByVal e As CancelEventArgs)
            e.Cancel = True
            Me.ShowHelp
        End Sub

        Private Sub OnHelpRequested(ByVal sender As Object, ByVal e As HelpEventArgs)
            Me.ShowHelp
        End Sub

        Private Sub RuleConditionDialog_FormClosing(ByVal sender As Object, ByVal e As FormClosingEventArgs)
            If (Me.wasOKed AndAlso (Not Me.syntaxException Is Nothing)) Then
                e.Cancel = True
                DesignerHelpers.DisplayError((Messages.Error_ConditionParser & ChrW(10) & Me.syntaxException.Message), Me.Text, Me.serviceProvider)
                If TypeOf Me.syntaxException Is RuleSyntaxException Then
                    Me.conditionTextBox.SelectionStart = DirectCast(Me.syntaxException, RuleSyntaxException).Position
                End If
                Me.conditionTextBox.SelectionLength = 0
                Me.conditionTextBox.ScrollToCaret
                Me.wasOKed = False
            End If
        End Sub

        Private Sub ShowHelp()
            If (Not Me.serviceProvider Is Nothing) Then
                Dim service As IHelpService = [TryCast](Me.serviceProvider.GetService(GetType(IHelpService)),IHelpService)
                If (Not service Is Nothing) Then
                    service.ShowHelpFromKeyword((MyBase.GetType.FullName & ".UI"))
                Else
                    Dim service2 As IUIService = [TryCast](Me.serviceProvider.GetService(GetType(IUIService)),IUIService)
                    If (Not service2 Is Nothing) Then
                        service2.ShowError(Messages.NoHelp)
                    End If
                End If
            Else
                Dim service3 As IUIService = DirectCast(Me.GetService(GetType(IUIService)), IUIService)
                If (Not service3 Is Nothing) Then
                    service3.ShowError(Messages.NoHelp)
                End If
            End If
        End Sub


        ' Properties
        Public ReadOnly Property Expression As CodeExpression
            Get
                Return Me.ruleExpressionCondition.Expression
            End Get
        End Property


        ' Fields
        Private cancelButton As Button
        Private components As IContainer
        Private conditionErrorProvider As ErrorProvider
        Private conditionLabel As Label
        Private conditionTextBox As IntellisenseTextBox
        Private headerLabel As Label
        Private headerPictureBox As PictureBox
        Private okButton As Button
        Private okCancelTableLayoutPanel As TableLayoutPanel
        Private ruleExpressionCondition As RuleExpressionCondition
        Private ruleParser As Parser
        Private serviceProvider As IServiceProvider
        Private syntaxException As Exception
        Private wasOKed As Boolean
    End Class
End Namespace

